/**
 * 单元名称：图片处理方法
 * 单元功能：对图片进行压缩、添加水印
 * 所属模块功能：
 * 创建人：yan
 * 创建时间：230823
 * 修改人：
 * 修改时间：
 */


/**
 * 图片文件压缩
 * @param file 图片文件
 * @param opts 添加文字水印参数
 * @description
 *  1、将文件转img对象
 *  2、获取文件宽高比例
 *  3、自定义等比例缩放宽高属性，这里我用的是固定220000面积，高度是等比例缩放
 *  4、判断是否有opts添加文字水印参数，有则调用添加文字水印方法
 *  5、canvas重新绘制图片
 *  6、canvas转二进制对象转文件对象，返回
 *
 * @return {Promise<*>}
 */
export const imgCompress = async (file,opts) => {
  const img = await file2Img(file);
  return new Promise((resolve,reject) => {
    const canvas = document.createElement('canvas'),
      context = canvas.getContext('2d');
    //  获取文件宽高比例
    const {width: originWidth, height: originHeight} = img;
    //  自定义等比例缩放宽高属性， 固定面积220000，宽度高度等比例缩放
    const scale = +(originWidth /originHeight).toFixed(2) //比例取小数点后两位
    const s = 220000,
      targetWidth = Math.round(Math.sqrt(scale * s)),
      targetHeight = Math.round(targetWidth / scale);

    canvas.width = targetWidth
    canvas.height = targetHeight
    context.clearRect(0, 0, targetWidth, targetHeight)
    // canvas重新绘制图片
    context.drawImage(img, 0, 0, targetWidth, targetHeight)

    if (opts){
      fillText(context,opts,targetWidth,targetHeight);
    }

    // canvas转二进制对象转文件对象，返回
    const type = 'image/png'
    canvas.toBlob(blob => {
      const f = new File([blob], file.name, {
        type,
        lastModified: file.lastModified
      })
      resolve(f)
    }, type)


  })
}

/**
 * 图片file转化成img对象
 * @param file
 * @return {Promise<any>}
 */
export const  file2Img = (file) => {
  return new Promise((resolve,reject) => {
    const img = new Image(),
      reader = new FileReader();
    reader.onload = e => img.src = e.target.result;
    reader.onerror = e => reject(e);
    reader.readAsDataURL(file);
    img.onload = () => resolve(img);
    img.onerror = (e) => reject(e);
  })
}

/**
 * 图片添加水印
 * @param file 图片文件
 * @param opts 添加文字水印参数
 * @description 没有进行压缩处理的图片直接添加水印
 * @return {Promise<*>}
 */
export const addWatermark = async (file,opts) => {
  const img = await file2Img(file);
  return new Promise((resolve,reject) => {
    const canvas = document.createElement('canvas'),
      context = canvas.getContext('2d');
    //  获取文件宽高比例
    const {width: originWidth, height: originHeight} = img;
    canvas.width = originWidth
    canvas.height = originHeight;

    context.clearRect(0, 0, originWidth, originHeight)
    // canvas重新绘制图片
    context.drawImage(img, 0, 0, originWidth, originHeight)

    fillText(context,opts,originWidth,originHeight);

    // canvas转二进制对象转文件对象，返回
    const type = 'image/png'
    canvas.toBlob(blob => {
      const f = new File([blob], file.name, {
        type,
        lastModified: file.lastModified
      })
      resolve(f)
    }, type)
  })
}

/**
 * 画布画文字
 * @param ctx canvas上下文
 * @param opts {Array} 定义文字参数数组
 * opts: {
 *   textAlign: // 水印文字的对齐方式
 *   font: "16px Microsoft Yahei", // 水印文字的字体
 *   textBaseline: "middle", // 水印文字的基线
 *   fillStyle: "rgba(184, 184, 184, 0.6)", // 水印文字的填充样式
 *   content: '名称', // 水印文字的内容
 *   rotate: -30, // 水印文字的旋转角度
 *   zIndex: 10000, // 水印的 z-index 值
 *   position: {
 *     top: 0,
 *     left: 0,
 *     right: 0,
 *     bottom: 0
 *   }
 *   top: '',   //水印位置top
 *   left: '',  //水印位置right
 * }
 * @param width 画布宽度
 * @param height 画布高度
 */
export const fillText = (ctx,opts, width ,height) =>{
  opts.forEach(item => {
    let {content,textAlign,font ,textBaseline ,fillStyle ,rotate ,zIndex,position } = item;
    textAlign && (ctx.textAlign = textAlign);
    textBaseline && (ctx.textBaseline = textBaseline);
    ctx.font = font || '16px serif';
    ctx.fillStyle = fillStyle || '#ffffff';
    rotate && ctx.rotate((Math.PI / 180) * rotate);
    let x = 0,y = 0,
      metrics = ctx.measureText(content),
      textWidth = metrics.width,
      textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;

    if (position){
      let {left, top, bottom, right} = position;
      //计算文字位置
      x = right ? width - right - textWidth : 0;
      x = left ? left : x;  //left 优先于 right
      x = x > width ? width - textWidth : x;  //超出画布宽度
      x = x < 0 ? 0 : x;  //小于画布

      y = bottom ? height - bottom : 0;
      y = top ? top + textHeight : y;  //top 优先于 bottom
      y = y > height ? height : y < 0 ? 0 : y;  //超出画布宽度
    }
    console.log(x,y);
    console.log(width,height);
    //空心描边
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#000';
    ctx.strokeText(content, x, y);
    ctx.fillText(content,x,y);// 绘制文字，实心填充

  })
}

/**
 * base64转化成图片
 * @param dataurl 图片地址base64
 * @param fileName 图片名称
 */
export const base64ImgtoFile = (dataurl, fileName='file') =>{
  const arr = dataurl.split(",");
  const mime = arr[0].match(/:(.*?);/)[1];
  const suffix = mime.split('/')[1]
  const bstr = atob(arr[1]);
  let n = bstr.length;
  var u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], `${fileName}.${suffix}`, { type: mime });
}


